import { Module, Global } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ExceptionService } from './exception.service';
import {
  ExceptionFilterInterface,
  ExceptionReporterInterface,
  ExceptionStatsInterface,
} from './exception.interface';

/**
 * 异常处理模块
 * 基于 NestJS 官方示例实现
 * 参考: https://docs.nestjs.cn/fundamentals/exception-filters
 * 对应 Java: 异常处理配置
 */
@Global()
@Module({
  imports: [ConfigModule],
  providers: [
    {
      provide: 'EXCEPTION_FILTER_PROVIDER',
      useFactory: (configService: ConfigService) => {
        // 这里会根据配置选择具体的异常过滤器实现
        // 默认使用全局异常过滤器
        return {
          async catch(exception: any, context: any): Promise<void> {
            console.error('[EXCEPTION_FILTER]', exception.message, context);
          },
          async handle(exception: any, context: any): Promise<any> {
            return {
              statusCode: 500,
              message: exception.message || 'Internal server error',
              timestamp: new Date().toISOString(),
              path: context?.request?.url,
            };
          },
        };
      },
      inject: [ConfigService],
    },
    {
      provide: 'EXCEPTION_REPORTER_PROVIDER',
      useFactory: (configService: ConfigService) => {
        // 异常上报实现
        return {
          async report(exception: any, context?: any): Promise<void> {
            console.error('[EXCEPTION_REPORTER]', exception.message, context);
          },
          async reportError(error: Error, context?: any): Promise<void> {
            console.error(
              '[EXCEPTION_REPORTER]',
              error.message,
              error.stack,
              context,
            );
          },
        };
      },
      inject: [ConfigService],
    },
    {
      provide: 'EXCEPTION_STATS_PROVIDER',
      useFactory: (configService: ConfigService) => {
        // 异常统计实现
        const stats = {
          total: 0,
          byType: new Map<string, number>(),
          byTime: new Map<string, number>(),
        };
        return {
          async record(exception: any): Promise<void> {
            stats.total++;
            const type = exception.constructor.name;
            stats.byType.set(type, (stats.byType.get(type) || 0) + 1);

            const hour = new Date().toISOString().substring(0, 13);
            stats.byTime.set(hour, (stats.byTime.get(hour) || 0) + 1);
          },
          async getStats(): Promise<any> {
            return {
              total: stats.total,
              byType: Object.fromEntries(stats.byType),
              byTime: Object.fromEntries(stats.byTime),
            };
          },
        };
      },
      inject: [ConfigService],
    },
    ExceptionService,
  ],
  exports: [ExceptionService],
})
export class ExceptionModule {}
